import cv2
import numpy as np
import matplotlib.pyplot as plt
import os

plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

# 创建"char"文件夹（如果不存在）
if not os.path.exists('char'):
    os.makedirs('char')

# 读取原图
img = cv2.imread('hanzi1.jpg')
# 读取彩色图像
rgb_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)  # 将BGR格式转换为RGB格式

# 定义裁剪区域的坐标
x, y, w, h = 0, 450, 3000, 3400  # 以左上角（0,450）为起点，定义宽高为3000x3400的区域

# 裁剪图像
cropped_img = rgb_img[y:y+h, x:x+w]

# 将图像转换为灰度图像
gray_img = cv2.cvtColor(cropped_img, cv2.COLOR_RGB2GRAY)  # 将彩色图像转换为灰度图像
binary_img = cv2.threshold(gray_img, 127, 255, cv2.THRESH_BINARY_INV)[1]  # 对灰度图像进行二值化处理

# 创建结构元素
kernel = np.ones((3, 3), np.uint8)  # 创建一个3x3的矩形结构元素，用于开运算
eroded_img = cv2.erode(binary_img, kernel, iterations=3)  # 腐蚀

median_filtered_img = cv2.medianBlur(eroded_img, 5)  # 中值滤波去小白点
dilated_img = cv2.dilate(median_filtered_img, kernel, iterations=3)  # 膨胀

# 进行闭运算
closed_img = cv2.morphologyEx(dilated_img, cv2.MORPH_CLOSE, kernel, iterations=30)

# Canney边缘检测
img_blur = cv2.GaussianBlur(closed_img, (3, 3), 0)  # 高斯滤波
edges_with_blur = cv2.Canny(img_blur, 50, 200)

# 得到图像轮廓列表
contours, _ = cv2.findContours(edges_with_blur, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

# 复制图像以绘制边界框
img_copy = cropped_img.copy()

# 遍历轮廓列表
for index, c in enumerate(contours):
    perimeter = cv2.arcLength(c, True)
    x, y, w, h = cv2.boundingRect(c)
    cv2.rectangle(rgb_img, (x, y), (x + w, y + h), (0, 255, 0), 2)

    # 根据周长阈值筛选并绘制边界框
    if perimeter > 100:
        char_img = cropped_img[y:y+h, x:x+w]  # 提取汉字图像
        char_filename = os.path.join('char', f'char_{index+1}.jpg')  # 生成文件名
        cv2.imwrite(char_filename, char_img)  # 保存汉字图像

# 创建包含3个子图的画布
fig, ax = plt.subplots(1, 7, figsize=(30, 15))

ax[0].imshow(gray_img, cmap='gray')
ax[0].set_title(f"原图灰度图", size=6)
ax[1].imshow(binary_img, cmap='gray')
ax[1].set_title(f"进行全局阈值处理，生成二值化图", size=6)
ax[2].imshow(eroded_img, cmap='gray')
ax[2].set_title(f"应用腐蚀操作，去除噪点", size=6)
ax[3].imshow(dilated_img, cmap='gray')
ax[3].set_title(f"应用膨胀操作，突出图像特征，中值滤波去除小白点", size=6)
ax[4].imshow(closed_img, cmap='gray')
ax[4].set_title(f"进行闭运算，连接断开的部分", size=6)
ax[5].imshow(edges_with_blur, cmap='gray')
ax[5].set_title(f"Canny边缘检测", size=6)
ax[6].imshow(rgb_img)
ax[6].set_title(f"汉字边界框绘制", size=6)

# 隐藏坐标轴
for i in range(7):
    ax[i].axis('off')

# 保存图像
plt.savefig('output.png', dpi=300)

# 显示图像
plt.show()